/********************************************************/
/*	vec3 class by George Chew							*/
/*	For use in GeorgeLib								*/
/*	Created Mar 2013									*/
/*														*/
/*	Version 0001										*/
/********************************************************/

#ifndef __VEC3_H__
#define __VEC3_H__

#include "stdafx.h"
#define _USE_MATH_DEFINES
#include <math.h>

#define RADTODEG 180.0f/(float)M_PI
#define DEGTORAD (float)M_PI/180.0f
#define ZEROTOLERANCE 0.00001
#define ZEROTOLERANCEDIGITS 5


	/*		How to use this class		*/
	// vec3 myVec(42,69,9001);
	// float myArr[3]; myVec.asArray(myArr);
	// std::cout << myVec << std::endl;

class vec3
{
public:
	float x, y, z;

public:
	/* Constructors and Destructor */
	vec3	(void);							// constructor : an empty vector, (0,0,0)
	vec3	(float X, float Y, float Z);	// constructor : from three values, (x,y,z)
	vec3	(float a);						// constructor : from one value, (a,a,a)
	vec3	(float * v);					// constructor : from an array of float[3]
	vec3	(vec3 &v);						// constructor : from another vector
	~vec3	(void);							// destructor

	/* Class Accessors */
	float	total			(void);			// addition of all the values of the vector
	vec3	negated			(void);			// negative of this vector
	void	asArray			(float *arr);	// values of this vector to an array

	/* Vector Calculations */
	float	magnitude		(void);			// magnitude of this vector
	vec3	normal			(void);			// unit vector of this vector
	void	normalize		(void);			// set this vector as its unit vector
	vec3	direction		(void);			// angles between (1,1,1) and this vector on each axis in degrees
	float	distancebetween	(vec3 v);		// distance between this vector and v
	float	distancesquared	(vec3 v);		// distance squared between this vector and v
	float	anglebetween	(vec3 v);		// angle between this vector and v
	float	dotproduct		(vec3 v);		// dot product between this vector and v
	vec3	crossproduct	(vec3 v);		// cross product between this vector and v
	vec3	rotateabout		(float angle, vec3 axis);	// rotate this vector about an arbitrary axis
	vec3	reflect			(vec3 normal);	// reflection vector about a surface normal

	/* Operator Overloads */
	vec3	operator+		(vec3 v);		// add vector v to this vector
	void	operator+=		(vec3 v);		// add vector v to this vector
	vec3	operator-		(vec3 v);		// subtract vector v from this vector
	void	operator-=		(vec3 v);		// subtract vector v from this vector
	vec3	operator*		(float f);		// multiply this vector by f
	void	operator*=		(float f);		// multiply this vector by f
	vec3	operator/		(float f);		// divide this vector by f
	void	operator/=		(float f);		// divide this vector by f
	float	operator*		(vec3 v);		// dot product between this vector and vector v
	vec3	operator^		(vec3 v);		// cross product between this vector and vector v

	/* Comparison Operator Overloads */
	bool	operator==		(vec3 v);		// checks if vector is equal to another vector
	bool	operator!=		(vec3 v);		// checks if vector is not equal to another vector
	bool	operator>		(vec3 v);		// checks if vector magnitude is more than another vector's magnitude
	bool	operator>=		(vec3 v);		// checks if vector magnitude is more than or equal to another vector's magnitude
	bool	operator<		(vec3 v);		// checks if vector magnitude is less than another vector's magnitude
	bool	operator<=		(vec3 v);		// checks if vector magnitude is less than or equal to another vector's magnitude

	// values input using operator()
	void	operator()		(float X, float Y, float Z);
	void	operator()		(vec3 v);

	// get values using [] operator
	float	operator[]		(int a);

	// negative value of vector
	friend	vec3			operator-		(vec3 v);

	// output vector contents to console
	friend	ostream&		operator<<		(ostream &os, vec3 &v);

	// round up numbers to 5 digits after the decimal point
	friend	vec3			detectzero		(vec3 vector);
};

typedef const vec3 cvec3;

#endif // __VEC3_H__ //